﻿using System;
using System.IO;
using gixoom.Dom;
using gixoom.Dom.Block;
using gixoom.Dom.Storage.Block;
using gixoom.Target.WcfWsHttp.Attributes;
using gixoom.Target.WcfWsHttp.Properties;
using Ninject;
using Ninject.Modules;

namespace gixoom.Target.WcfWsHttp
{
    internal class gixoomWcfWsHttpTargetModule : NinjectModule
    {
        public override void Load()
        {
            Bind<IKernel>().ToConstant(Kernel);
            Bind<string>().ToConstant(Resources.NamegixoomWcfWsHttpTarget).
                WhenTargetHas<gixoomWcfWsHttpTargetNameAttribute>();

            var domFacade = CreategixoomDomFacade();
            BindBlockFacade(domFacade);
            BindBlockStorage(domFacade);

            Bind<ITargetBlockStorage>().To<TargetBlockStorage>().InSingletonScope();
        }

        private void BindBlockFacade(IgixoomDomFacade domFacade)
        {
            var blockFacade = domFacade.GetBlockFacade();
            Bind<IBlockFacade>().ToConstant(blockFacade);
        }

        private void BindBlockStorage(IgixoomDomFacade domFacade)
        {
            var blockStorageFacade = domFacade.GetBlockStorageFacade();
            string applicationDataPath = Environment.GetFolderPath(
                Environment.SpecialFolder.ApplicationData);
            string filesPath = EnsureSlashInTheEnd(applicationDataPath) +
                EnsureSlashInTheEnd(Resources.NamegixoomFolder) +
                EnsureSlashInTheEnd(Resources.NameBlocksFolder);

            if (!Directory.Exists(filesPath))
            {
                var directoryInfo = CreateDirectory(filesPath);

                if (directoryInfo == null)
                {
                    throw new Exception("Cannot create the directory: \"" + filesPath + "\"");
                }
            }

            var blockStorage = blockStorageFacade.CreateFilesBlockStorage(filesPath);
            Bind<IBlockStorage>().ToConstant(blockStorage);
        }

        private IgixoomDomFacade CreategixoomDomFacade()
        {
            // TODO: hosts should be transmitted in some other way,
            // not via gixoomDomModule constructor because here they are not needed
            var domModule = new gixoomDomModule(new string[] {});
            var domKernel = new StandardKernel(domModule);
            var domFacade = new gixoomDomFacade(domKernel);

            return domFacade;
        }

        private DirectoryInfo CreateDirectory(string path)
        {
            DirectoryInfo directoryInfo = null;

            // TODO: all exceptions should be properly processed
            try
            {
                directoryInfo = Directory.CreateDirectory(path);
            }
            catch
            {
            }

            return directoryInfo;
        }

        private string EnsureSlashInTheEnd(string s)
        {
            string result = (s[s.Length - 1] == '\\') ?
                s : s + '\\';

            return result;
        }
    }
}
